package com.gis507.mapreduce.Utils;

import com.gis507.mapreduce.AISBean.AisClassifyBean;
import com.gis507.mapreduce.AISBean.AnalysisIndex;
import com.gis507.test.AISDataToMysql.AISInterBean;
import lombok.extern.slf4j.Slf4j;
import org.gavaghan.geodesy.Ellipsoid;
import org.gavaghan.geodesy.GeodeticCalculator;
import org.gavaghan.geodesy.GeodeticCurve;
import org.gavaghan.geodesy.GlobalCoordinates;
import org.junit.Test;

import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;

@Slf4j
public class UtilsClass {

    /**
     *
     *
     * @param str
     * @return
     */
    public static String getNotNull(String str){

        if (!str.isEmpty() )
            return str;
        else
            return "0";
    }

    /**
     * String to Double
     * @param str
     * @return
     */
    public static double turnToDouble(String str){

        return Double.parseDouble(getNotNull(str));
    }

    /**
     * String to Int
     * @param str
     * @return
     */
    public static int turnToInt(String str){
        return Integer.parseInt(getNotNull(str));
    }

    /**
     * String to Long
     * @param str
     * @return
     */
    public static long turnToLong(String str){

        return Long.parseLong(getNotNull(str));
    }

    /**
     * Determine the sea area
     * @param ais
     * @return  1:渤海范围 2:黄海范围 3:东海范围 4:南海范围 5:西太平洋范围 6:日本海范围 0:主要为东南亚海域，及其他少数海域间空隙
     */
    public static int getSeaRangeNumber(AisClassifyBean ais){

        double lon = ais.getLon_d();
        double lat = ais.getLat_d();

        if (lon >= 117.58 && lon <= 121.17 && lat >= 37.12 && lat <= 41)  //渤海范围
            return 1;
        else if (lon>=120 && lon<=123 && lat>=35 && lat<=45)    //黄海范围
            return 2;
        else if (lon>=117.18 && lon<=131 && lat>=23 && lat<=35.17)  //东海范围
            return 3;
        else if (lon>=105 && lon<=118 && lat>=4 && lat<=21)     // 南海范围
            return 4;
        else if (lon>=99 && lon<=148 && lat>=-10 && lat<=50)    //西太平洋范围
            return 5;
        else if (lon>=141.15 && lon<=148 && lat>=29.73 && lat<=50)  //日本海范围
            return 6;
        else return 0;  //主要为东南亚海域，及其他少数海域间空隙

    }

    /**
     * clone a new AISClassifyBean from a old AISClassifyBean
     * @param aisMaster
     * @return
     */
    public static AisClassifyBean getNewAisClassifyBean(AisClassifyBean aisMaster){

        AisClassifyBean aisSlave = new AisClassifyBean();

        //String mmsi, String shipType, String nacStatusCN, double draught,
        // double heading, double course, double speed, String dest,
        // long unixTime, double lon_d, double lat_d, int seaRange
        aisSlave.setMmsi(aisMaster.getMmsi());
        aisSlave.setShipType(aisMaster.getShipType());
        aisSlave.setNacStatusCN(aisMaster.getNacStatusCN());
        aisSlave.setLength(aisMaster.getLength());
        aisSlave.setWidth(aisMaster.getWidth());
        aisSlave.setDraught(aisMaster.getDraught());
        aisSlave.setHeading(aisMaster.getHeading());
        aisSlave.setCourse(aisMaster.getCourse());
        aisSlave.setSpeed(aisMaster.getSpeed());
        aisSlave.setDest(aisMaster.getDest());
        aisSlave.setUnixTime(aisMaster.getUnixTime());
        aisSlave.setLon_d(aisMaster.getLon_d());
        aisSlave.setLat_d(aisMaster.getLat_d());
        aisSlave.setSeaRange(aisMaster.getSeaRange());
        aisSlave.setTonnge(aisMaster.getTonnge());

        return aisSlave;
    }

    public static AnalysisIndex getNewAnalysisIndex(AnalysisIndex aisMaster){

        AnalysisIndex aisSlave = new AnalysisIndex();

        //private String mmsi;
        //    private Long unixTime;
        //    private Double speed;
        //    private Double heading;     // 对地航向
        //    private Double course;      // 真航向
        //    private Double lon_d;
        //    private Double lat_d;
        //    private Double distance;    // 距离
        //    private Double diffTime;
        //    private Double diffSpeed;
        //    private Double diffHeading;
        //    private Double diffCourse;
        aisSlave.setMmsi(aisMaster.getMmsi());
        aisSlave.setUnixTime(aisMaster.getUnixTime());
        aisSlave.setSpeed(aisMaster.getSpeed());
        aisSlave.setHeading(aisMaster.getHeading());
        aisSlave.setCourse(aisMaster.getCourse());
        aisSlave.setSpeed(aisMaster.getSpeed());
        aisSlave.setLon_d(aisMaster.getLon_d());
        aisSlave.setLat_d(aisMaster.getLat_d());
        aisSlave.setDistance(aisMaster.getDistance());
        aisSlave.setDiffTime(aisMaster.getDiffTime());
        aisSlave.setDiffSpeed(aisMaster.getDiffSpeed());
        aisSlave.setDiffHeading(aisMaster.getDiffHeading());
        aisSlave.setDiffCourse(aisMaster.getDiffCourse());

        return aisSlave;
    }

    /**
     * judging whether the speed is over range
     * @return true:未超限  false:超限
     */
    public static boolean judgeSpeed(AisClassifyBean ais,double minSpeed,double maxSpeed){

        if (ais.getSpeed() < maxSpeed && ais.getSpeed() > minSpeed){
            return true;
        }else {
            return false;
        }
    }

    /**
     * 插值
     * @param ais1
     * @param ais2
     * @return
     */
    public static ArrayList<AisClassifyBean> insertPoint(AisClassifyBean ais1, AisClassifyBean ais2,double standStance) {

        //获得实际距离
        double stance = getStance(ais1, ais2);
        //按照距离进行插值，需要插入点的个数
        double number = Math.floor(stance / standStance) - 1;

        //实例化一个列表，将所有添加的数据放大集合中
        ArrayList<AisClassifyBean> aisInsertList = new ArrayList<>();

        //插入的点放入集合中
        for (int i = 1; i <= number; i++) {

            //speed就应该是大于ais1，并且小于ais2
            double speed = getDecimal(2,ais1.getSpeed() + (ais2.getSpeed() - ais1.getSpeed()) * i / (number + 1));

            //插入点的lat和lon
            double lat = getDecimal(6,ais1.getLat_d() + (ais2.getLat_d() - ais1.getLat_d()) * i / (number + 1));
            double lon = getDecimal(6,ais1.getLon_d() + (ais2.getLon_d() - ais1.getLon_d()) * i / (number + 1));

            //时间
            //Math.round():Double类型转换为Long
            //long转换为double,(double)long;
            Long unixTime = Math.round(ais1.getUnixTime() + (ais2.getUnixTime() - ais1.getUnixTime()) * i / (number + 1));

            //course,rot等其他字段，都采用ais1的
            //String mmsi, String shipType, String nacStatusCN, double draught,
            // double heading, double course, double speed, String dest,
            // long unixTime, double lon_d, double lat_d, int seaRange
            String mmsi = ais1.getMmsi();
            String shioType = ais1.getShipType();
            String nacStatusCN = ais1.getNacStatusCN();
            double draught = ais1.getDraught();
            double heading = ais1.getHeading();
            double course = ais1.getCourse();
            String dest = ais1.getDest();
            int seaRange = ais1.getSeaRange();
            double length = ais1.getLength();
            double width = ais1.getWidth();
            double tonnage = ais1.getTonnge();
            //封装到aisData中
            AisClassifyBean aisData = new AisClassifyBean(mmsi,shioType,nacStatusCN,length,width,draught,heading,course,speed,
                    dest,unixTime,lon,lat,seaRange,tonnage);

            //输出插值得到的点
            log.info("插值得到的点：" + aisData);
            //放到列表中
            aisInsertList.add(aisData);

        }

        //返回列表
        return aisInsertList;
    }

    /**
     * 求解两个坐标之间的距离
     *
     * @param gpsFrom   第一个点坐标
     * @param gpsTo     第二个点坐标
     * @param ellipsoid 使用的坐标系
     * @return
     */
    public static double getDistanceMeter(GlobalCoordinates gpsFrom, GlobalCoordinates gpsTo, Ellipsoid ellipsoid) {
        //创建GeodeticCalculator，调用计算方法，传入坐标系、经纬度用于计算距离
        GeodeticCurve geoCurve = new GeodeticCalculator().calculateGeodeticCurve(ellipsoid, gpsFrom, gpsTo);

        return geoCurve.getEllipsoidalDistance();
    }


    /**
     * 求得距离
     */
    public static double getStance(AisClassifyBean ais1, AisClassifyBean ais2) {


        GlobalCoordinates source = new GlobalCoordinates(ais1.getLat_d(), ais2.getLon_d());
        GlobalCoordinates target = new GlobalCoordinates(ais2.getLat_d(), ais2.getLon_d());


        double meter = getDistanceMeter(source, target, Ellipsoid.WGS84);

        return meter;
    }

    /**
     * AnalysisIndex求距离
     * @param ais1
     * @param ais2
     * @return
     */
    public static double getDisStance(AnalysisIndex ais1, AnalysisIndex ais2) {


        GlobalCoordinates source = new GlobalCoordinates(ais1.getLat_d(), ais2.getLon_d());
        GlobalCoordinates target = new GlobalCoordinates(ais2.getLat_d(), ais2.getLon_d());


        double meter = getDistanceMeter(source, target, Ellipsoid.WGS84);

        return meter;
    }

    /**
     * 获取小数点后几位有效数字
     * @param i 小数点后几位
     * @param j 小数double
     * @return
     */
    public static double getDecimal(int i,double j){
        if (i == 2){

            DecimalFormat df = new DecimalFormat("#.##");
            return Double.parseDouble(df.format(j));
        }else if (i == 6){
            DecimalFormat df = new DecimalFormat("#.######");
            return Double.parseDouble(df.format(j));
        }
        return 0;
    }

//    public static double getTonnage(AisClassifyBean aisClassifyBean){
//        double para = 0.33;   //方模系数
//        if("Fishing".equals(aisClassifyBean.getShipType())){
//            //捕捞
//            para= 0.391;
//        }
//        else if ("Pilot vessel".equals(aisClassifyBean.getShipType())){
//            //引航船
//            para= 0.372;
//        }else if ("Search and rescue vessel".equals(aisClassifyBean.getShipType())){
//            //搜救船
//            para= 0.35;
//        }else if ("Tug".equals(aisClassifyBean.getShipType())){
//            //拖轮
//            para= 0.26;
//        }else if ("Pleasure craft".equals(aisClassifyBean.getShipType())){
//            //娱乐船
//            para= 0.25;
//        }else if ("WIG".equals(aisClassifyBean.getShipType())){
//            //地效应船
//            para= 0.28;
//        }else if ("Passenger ship".equals(aisClassifyBean.getShipType())){
//            //客船
//            para= 0.358;
//        }else if ("Cargo ship".equals(aisClassifyBean.getShipType())){
//            //货船
//            para= 0.68;
//        }else if ("Tanker".equals(aisClassifyBean.getShipType())){
//            //油轮
//            para= 0.70;
//        }else{
//            //其他
//            para= 0.33;
//        }
//
//        Double length = aisClassifyBean.getLength();
//        Double width = aisClassifyBean.getWidth();
//        Double draught = aisClassifyBean.getDraught();
//        return (length * width * draught * para)/0.9756;
//    }

    public static double getTonnage(String shipType,double length,double width,double draught){
        double para = 0.33;   //方模系数
        if("Fishing".equals(shipType)){
            //捕捞
            para= 0.391;
        }
        else if ("Pilot vessel".equals(shipType)){
            //引航船
            para= 0.372;
        }else if ("Search and rescue vessel".equals(shipType)){
            //搜救船
            para= 0.35;
        }else if ("Tug".equals(shipType)){
            //拖轮
            para= 0.26;
        }else if ("Pleasure craft".equals(shipType)){
            //娱乐船
            para= 0.25;
        }else if ("WIG".equals(shipType)){
            //地效应船
            para= 0.28;
        }else if ("Passenger ship".equals(shipType)){
            //客船
            para= 0.358;
        }else if ("Cargo ship".equals(shipType)){
            //货船
            para= 0.68;
        }else if ("Tanker".equals(shipType)){
            //油轮
            para= 0.70;
        }else{
            //其他
            para= 0.33;
        }

        return getDecimal(2,((length * width * draught * para)/0.9756));
    }

    public static Long getTime(String string, SimpleDateFormat sdf) throws ParseException {


        Long time =  sdf.parse(string).getTime();
        return time;
    }



    @Test
    public void test(){
        AisClassifyBean ais1 = new AisClassifyBean();
        AisClassifyBean ais2 = new AisClassifyBean();
        ais1.setLon_d(109.1209);
        ais1.setLat_d(18.356);
        ais2.setLon_d(1179);
        ais2.setLat_d(18.3458);
        double stance = getStance(ais1, ais2);
        System.out.println(stance);
    }
}
